package com.hfb.mashibing.alip8.juc;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ConcurrentHashMap 的源码分析:
 *
 * 对比
 * 与HashMap的区别是什么？
 * ConcurrentHashMap是HashMap的升级版，HashMap是线程不安全的，而ConcurrentHashMap是线程安全。而其他功能和实现原理和HashMap类似。
 *
 * 与Hashtable的区别是什么？
 * Hashtable也是线程安全的，但每次要锁住整个结构，并发性低。相比之下，ConcurrentHashMap获取size时才锁整个对象。
 *
 * Hashtable对get/put/remove都使用了同步操作。ConcurrentHashMap只对put/remove同步。
 *
 * Hashtable是快速失败的，遍历时改变结构会报错ConcurrentModificationException。ConcurrentHashMap是安全失败，允许并发检索和更新。
 *
 * JDK8的ConcurrentHashMap和JDK7的ConcurrentHashMap有什么区别？
 *  JDK8中新增了红黑树
 *
 *  JDK7中使用的是头插法，JDK8中使用的是尾插法
 *
 *  JDK7中使用了分段锁，而JDK8中没有使用分段锁了
 *
 *  JDK7中使用了ReentrantLock，JDK8中没有使用ReentrantLock了，而使用了Synchronized
 *
 *  JDK7中的扩容是每个Segment内部进行扩容，不会影响其他Segment，而JDK8中的扩容和HashMap的扩容类似，只不过支持了多线程扩容，并且保证了线程安全
 *
 * 特性
 * ConcurrentHashMap是如何保证并发安全的？
 * JDK7中ConcurrentHashMap是通过ReentrantLock+CAS+分段思想来保证的并发安全的，ConcurrentHashMap的put方法会通过CAS的方式，把一个Segment对象存到Segment数组中，一个Segment内部存在一个HashEntry数组，相当于分段的HashMap，Segment继承了ReentrantLock，每段put开始会加锁。
 *
 * 在JDK7的ConcurrentHashMap中，首先有一个Segment数组，存的是Segment对象，Segment相当于一个小HashMap，Segment内部有一个HashEntry的数组，也有扩容的阈值，同时Segment继承了ReentrantLock类，同时在Segment中还提供了put，get等方法，比如Segment的put方法在一开始就会去加锁，加到锁之后才会把key,value存到Segment中去，然后释放锁。
 * 同时在ConcurrentHashMap的put方法中，会通过CAS的方式把一个Segment对象存到Segment数组的某个位置中。同时因为一个Segment内部存在一个HashEntry数组，所以和HashMap对比来看，相当于分段了，每段里面是一个小的HashMap，每段公用一把锁，同时在ConcurrentHashMap的构造方法中是可以设置分段的数量的，叫做并发级别concurrencyLevel.
 *
 * JDK8中ConcurrentHashMap是通过synchronized+cas来实现了。在JDK8中只有一个数组，就是Node数组，Node就是key，value，hashcode封装出来的对象，和HashMap中的Entry一样，在JDK8中通过对Node数组的某个index位置的元素进行同步，达到该index位置的并发安全。同时内部也利用了CAS对数组的某个位置进行并发安全的赋值。
 *
 * JDK8中的ConcurrentHashMap为什么使用synchronized来进行加锁？
 * JDK8中使用synchronized加锁时，是对链表头结点和红黑树根结点来加锁的，而ConcurrentHashMap会保证，数组中某个位置的元素一定是链表的头结点或红黑树的根结点，
 * 所以JDK8中的ConcurrentHashMap在对某个桶进行并发安全控制时，只需要使用synchronized对当前那个位置的数组上的元素进行加锁即可，对于每个桶，只有获取到了第一个元素上的锁，才能操作这个桶，不管这个桶是一个链表还是红黑树。
 *
 * 想比于JDK7中使用ReentrantLock来加锁，因为JDK7中使用了分段锁，所以对于一个ConcurrentHashMap对象而言，分了几段就得有几个ReentrantLock对象，表示得有对应的几把锁。
 *
 * 而JDK8中使用synchronized关键字来加锁就会更节省内存，并且jdk也已经对synchronized的底层工作机制进行了优化，效率更好。
 */
public class MyConcurrentHashMap {

    private ConcurrentHashMap<String,Object> map = new ConcurrentHashMap<>();

    public static void main(String[] args) {


    }
}
